#ifndef BUF_H
#define BUF_H

#include <stdarg.h>
#include <stdlib.h>
#include "macros.h"
#ifdef __cplusplus
#define _CPLUSPLUS
#endif
#define __cplusplus
#ifdef __STDC_LIMIT_MACROS
#define _STDC_LIMIT_MACROS
#endif
#undef __STDC_LIMIT_MACROS
#include <stdint.h>
#ifdef _STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#ifndef _CPLUSPLUS
#undef __cplusplus
#endif

#define BUF_NOMEM 1
#define BUF_PRINTF 2

typedef struct buf buf_t;

#define buf_acquire(b) do {                     \
    (b)->buf = NULL;                            \
    (b)->size = 0;                              \
    (b)->capacity = 0;                          \
  } while (0)

#define buf_release(b) do {                     \
    free((b)->buf);                             \
    (b)->buf = NULL;                            \
    (b)->size = 0;                              \
    (b)->capacity = 0;                          \
  } while (0)

int buf_encode_uint8(buf_t *, uint8_t);
int buf_encode_uint16(buf_t *, uint16_t);
int buf_encode_int32(buf_t *, int32_t);
int buf_encode_double(buf_t *, double);
int buf_encode_binary(buf_t *, void const *, size_t);
int buf_encode_printf(buf_t *, char const *, ...) format_printf(2, 3);

#define buf_encode_literal(b, s) (buf_encode_binary(b, s "", sizeof s - 1))

#define buf_elems(b) (0 ? NULL : (char const *) (b)->buf)
#define buf_size(b) (0 ? 0 : (b)->size)

#include "buf-private.h"

#endif
